home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1997 August / Walnut Creek CDROM.7z / VOL_400 / 466_01 / SRC / DOCEXPR.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1996-12-20  |  5.2 KB  |  310 lines

  1. #include <afx.h>
  2. #include <afxtempl.h>
  3. #include "parse.h"
  4. #include "input.h"
  5. #include "fmt.h"
  6. #include "docexpr.h"
  7. #include "errmsg.h"
  8.  
  9. #ifdef _DEBUG
  10. #define new DEBUG_NEW
  11. #endif
  12.  
  13.  
  14.  
  15. // *******************************************************
  16. // Implementation of CIDToken class
  17. // *******************************************************
  18.  
  19. //@doc DOCEXPR IDTOKEN
  20.  
  21. //@mfunc Search for text token in source string.
  22.  
  23.  
  24. int CIDToken::Eval(const char *szSrc)
  25. {
  26.     ASSERT(szSrc);
  27.  
  28.     if(m_sDocID.IsEmpty())
  29.         return TRUE;
  30.  
  31.     return strstr(szSrc, m_sDocID) != NULL;
  32. }
  33.  
  34.  
  35. // @mfunc Set the text token.
  36.  
  37. int CIDToken::Set(
  38.     const char *szToken,         //@parm Text for token.
  39.     const char *&szCont)        //@parm Where to continue after token.
  40. {
  41.     m_sDocID = chSpace;
  42.  
  43.     for(int i = 0; istagchar(szToken[i]) && i < MAXTAGSIZE; i++)
  44.         m_sDocID += szToken[i];
  45.  
  46.     if(istagchar(szToken[i]))
  47.         return exprerrDocTokenTooLong;
  48.  
  49.     m_sDocID += chSpace;
  50.  
  51.     szCont = szToken+i;
  52.  
  53.     m_sDocID.MakeUpper();
  54.  
  55.     return 0;
  56. }
  57.  
  58.  
  59. // *******************************************************
  60. // Implementation of CExprToken class
  61. // *******************************************************
  62.  
  63. //@doc DOCEXPR EXPRTOKEN
  64.  
  65. // @mfunc Evaluate the doc expression against
  66. // the source text.
  67.  
  68. int CExprToken::Eval(const char *szSrc)
  69. {
  70.     ASSERT(m_nOp != NONE);
  71.  
  72.     if(m_pLeft == NULL)
  73.         return TRUE;
  74.  
  75.     int nLeft = m_pLeft->Eval(szSrc);
  76.  
  77.     if(m_pRight == NULL)
  78.         return nLeft;
  79.  
  80.     int nRight = m_pRight->Eval(szSrc);
  81.  
  82.     switch(m_nOp)
  83.     {
  84.     case OR:
  85.         return nLeft || nRight;
  86.  
  87.     case AND:
  88.         return nLeft && nRight;
  89.     }
  90.  
  91.     return FALSE;
  92. }
  93.  
  94.  
  95. // @mfunc Construct an expression.
  96.  
  97. CExprToken::CExprToken(void)
  98. {
  99.     m_nOp = NONE;
  100.     m_pLeft = m_pRight = NULL;
  101.     m_bCommasAsOr = FALSE;
  102. }
  103.  
  104.  
  105. // @mfunc Construct an expression.
  106.  
  107. CExprToken::CExprToken(CTokenBase *pLeft, CTokenBase *pRight, int nOp)
  108. {
  109.     m_nOp = nOp;
  110.     m_pLeft = pLeft;
  111.     m_pRight = pRight;
  112.     m_bCommasAsOr = FALSE;
  113. }
  114.  
  115.  
  116. // @mfunc Kill an expression.
  117.  
  118. CExprToken::~CExprToken(void)
  119. {
  120.     Set();
  121. }
  122.  
  123.  
  124. int CExprToken::Set(void)
  125. {
  126.     m_nOp = OR;
  127.  
  128.     if(m_pLeft)
  129.     {
  130.         delete m_pLeft;
  131.         m_pLeft = NULL;
  132.     }
  133.     if(m_pRight)
  134.     {
  135.         delete m_pRight;
  136.         m_pRight = NULL;
  137.     }
  138.     
  139.     return 0;
  140. }
  141.  
  142. // @mfunc Parse a user-provided expression
  143. // (from command line or index statement).
  144. //
  145. // Expression consists of multiple tokens,
  146. // with optional subexpressions enclosed in
  147. // parentheses. 
  148. //
  149. // Valid operators are AND (&) or OR (\|).
  150. // A missing operator implies an OR.
  151.  
  152. int CExprToken::Set(
  153.     const char *szFind, 
  154.     const char *&szResume)
  155. {
  156. TRY
  157. {
  158.     ASSERT(szFind);
  159.  
  160.     CTokenBase *pNew;
  161.     CExprToken *pExpr;
  162.     int  nRet;
  163.     int  nOp;
  164.  
  165.     ExprParseState nState;
  166.  
  167.     // ************************* 
  168.     // Cleanup first.
  169.  
  170.     Set();
  171.  
  172.     // See if there is any expression.
  173.  
  174.     szFind = EatWhite(szFind);
  175.     if(*szFind == '\0')
  176.     {
  177.         szResume = szFind;
  178.         return 0;
  179.     }
  180.     
  181.     // ************************* 
  182.     // Parse.
  183.  
  184.     for(nState = LOOK_ARGUMENT;
  185.         *szFind;
  186.         szFind = EatWhite(szFind))
  187.     {
  188.         switch(nState)
  189.         {
  190.         case LOOK_OPERATOR:
  191.             // determine operator - if non specified, default is OR
  192.  
  193.             if(istagchar(*szFind))
  194.             {
  195.                 nOp = OR;
  196.             } 
  197.             else if(chPipe == *szFind || chOpenParen == *szFind ||
  198.                     (chComma == *szFind && m_bCommasAsOr))
  199.             {
  200.                 nOp = OR;
  201.                 
  202.                 if(*szFind != chOpenParen)
  203.                     szFind++;
  204.             }
  205.             else if(chAmpersand == *szFind)
  206.             {
  207.                 nOp = AND;
  208.                 szFind++;
  209.             }
  210.             else
  211.             {
  212.                 return exprerrExpectedExprOperator;
  213.             }
  214.  
  215.             nState = LOOK_ARGUMENT;
  216.  
  217.             break;
  218.  
  219.         case LOOK_ARGUMENT:
  220.  
  221.             // Figure out what kind of argument this
  222.             // is.
  223.  
  224.             if(istagchar(*szFind))
  225.             {
  226.                 pNew = new CIDToken;
  227.  
  228.                 // Set the values for the argument.        
  229.         
  230.                 nRet = pNew->Set(szFind, szResume);
  231.                 if(nRet)
  232.                     return nRet;
  233.  
  234.                 szFind = szResume;
  235.             }
  236.             else if(chOpenParen == *szFind)
  237.             {
  238.                 const char *szEnd;
  239.  
  240.                 pNew = new CExprToken;
  241.  
  242.                 szEnd = MatchParen(szFind, chCloseParen, TRUE);
  243.                 if(*szEnd != chCloseParen)
  244.                     return exprerrExprMismatchedParens;
  245.  
  246.                 CString sSubExpr(szFind+1, szEnd-szFind-1);
  247.  
  248.                 nRet = pNew->Set(sSubExpr, szResume);
  249.                  if(nRet)
  250.                     return nRet;
  251.  
  252.                 szFind = szEnd+1;
  253.             }
  254.             else
  255.             {
  256.                 return exprerrExpectedExprArgument;
  257.             }
  258.  
  259.             // If no arguments have been set in the expression,
  260.             // make this the left argument.
  261.             
  262.             if(m_pLeft == NULL)
  263.             {
  264.                 m_pLeft = pNew;
  265.             }
  266.  
  267.  
  268.             // If the left one has been set, but not the right,
  269.             // make this one the right argument.
  270.  
  271.             else if(m_pRight == NULL)
  272.             {
  273.                 m_nOp = nOp;
  274.                 m_pRight = pNew;
  275.             }
  276.  
  277.             // If both are set, collapse the left and right
  278.             // args into a sub expression. Establish this as the
  279.             // left argument and the new one as the right argument.
  280.  
  281.             else // (m_pLeft && m_pRight - both are filled)
  282.             {
  283.                 pExpr = new CExprToken(m_pLeft, m_pRight, m_nOp);
  284.             
  285.                 m_nOp    = nOp;
  286.                 m_pLeft  = pExpr;
  287.                 m_pRight = pNew;
  288.             }
  289.  
  290.             nState = LOOK_OPERATOR;
  291.  
  292.             break;
  293.         }
  294.     }
  295.  
  296.     if(nState == LOOK_ARGUMENT)
  297.         return exprerrExpectedExprArgument;
  298.  
  299.     szResume = szFind;
  300.  
  301.     return 0;
  302. }
  303. CATCH(CMemoryException, e)
  304. {
  305.     return errMemory;
  306. }
  307. END_CATCH
  308. }
  309.  
  310.